<script setup lang="ts">
import { useAutomationStore } from '@renderer/stores/automation'
import { ElMessage, ElMessageBox } from 'element-plus'
import { storeToRefs } from 'pinia'
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
import AppointmentSelectDialog from '../components/AppointmentSelectDialog.vue'
import { useAppStore } from '../stores/app'

// store: 自动化页面持久化状态（迁移到独立模块）
const appStore = useAppStore()
const automationStore = useAutomationStore()
const { config: automationConfig, selectedIds: automationSelectedIds, isRunning: automationIsRunning } = storeToRefs(automationStore)

// 响应式数据
// 已移除内联列表加载，保留运行状态与日志
const selectedAppointments = ref<any[]>([])
const showSelectDialog = ref(false)
const isRunning = ref(false)
const executionLogs = ref<Array<{ level: string, message: string, timestamp: string }>>([])
// 无人值守下一轮倒计时（由后端日志的“X 秒后”提示驱动）
const unattendedCountdown = ref(0)
let countdownTimer: number | null = null
let removeAutomationLogListener: (() => void) | null = null

// 音频报警（循环播放）
const alarmAudio = ref<HTMLAudioElement | null>(null)
const isAlarmPlaying = ref(false)
const isTtsSpeaking = ref(false)
// 10分钟内同一 key 不重复提醒
const remindedKeys = new Map<string, number>()
function shouldRemind(key: string, ttlMs?: number): boolean {
  const now = Date.now()
  const prev = remindedKeys.get(key)
  // 去重TTL固定为 10 分钟
  const ttl = typeof ttlMs === 'number' && ttlMs > 0
    ? ttlMs
    : 10 * 60_000 // 10分钟 = 600000ms
  if (prev && now - prev < ttl)
    return false
  remindedKeys.set(key, now)
  return true
}
function setupAlarmAudio() {
  try {
    const url = new URL('../assets/audio/fanghao.mp3', import.meta.url).href
    const audio = new Audio(url)
    audio.loop = true
    audio.volume = 1
    audio.addEventListener('play', () => {
      isAlarmPlaying.value = true
    })
    audio.addEventListener('pause', () => {
      isAlarmPlaying.value = false
    })
    alarmAudio.value = audio
  }
  catch {}
}
async function playAlarm(): Promise<void> {
  try {
    if (isAlarmPlaying.value)
      return
    if (!alarmAudio.value) {
      setupAlarmAudio()
    }
    if (alarmAudio.value) {
      await alarmAudio.value.play()
      isAlarmPlaying.value = true
    }
  }
  catch {}
}
function stopAlarm(): void {
  try {
    if (alarmAudio.value) {
      alarmAudio.value.pause()
      alarmAudio.value.currentTime = 0
      isAlarmPlaying.value = false
    }
    // 停止 TTS
    try {
      const synth = (window as any).speechSynthesis
      if (synth)
        synth.cancel()
    }
    catch {}
    isTtsSpeaking.value = false
  }
  catch {}
}

// 已前置

// 自动化选项（移除提醒设置，改为全局配置）
const automationOptions = automationConfig

// TTS 播报
function speak(text: string) {
  try {
    const synth = (window as any).speechSynthesis
    if (!synth) {
      return
    }
    try {
      synth.cancel()
    }
    catch {}
    const utter = new (window as any).SpeechSynthesisUtterance(text)
    utter.lang = 'zh-CN'
    utter.rate = 1
    utter.onstart = () => {
      isTtsSpeaking.value = true
    }
    utter.onend = () => {
      isTtsSpeaking.value = false
    }
    utter.onerror = () => {
      isTtsSpeaking.value = false
    }
    synth.speak(utter)
  }
  catch {}
}

// 2秒聚合合并队列
const pendingReminds: Array<{ date: string, count: number, inDnd: boolean }> = []
let pendingTimer: number | null = null
async function flushReminds(): Promise<void> {
  try {
    if (pendingReminds.length === 0)
      return
    // 聚合同日期计数
    const byDate = new Map<string, number>()
    let anyDnd = true
    for (const it of pendingReminds) {
      byDate.set(it.date, (byDate.get(it.date) || 0) + it.count)
      anyDnd = anyDnd && it.inDnd
    }
    const parts: string[] = []
    for (const [d, c] of byDate.entries()) {
      parts.push(`${d} ${c} 个`)
    }
    const body = parts.join('；') || '有可预约时段'
    // 通知
    try {
      await window.api.system.notifyAvailable('发现可预约', body)
    }
    catch {}
    // 任务栏 & 声音 & TTS（免打扰不执行声音/闪烁）
    if (!anyDnd) {
      try {
        await window.api.system.attention(true, '有可预约')
      }
      catch {}
      try {
        speak(`发现可预约：${body.replace(/；/g, '，')}`)
      }
      catch {}
      try {
        await playAlarm()
      }
      catch {}
      setTimeout(async () => {
        try {
          await window.api.system.attention(false)
        }
        catch {}
      }, 2000)
    }
  }
  finally {
    pendingReminds.length = 0
    pendingTimer = null
  }
}
function queueRemind(dateKey: string, count: number, inDnd: boolean): void {
  pendingReminds.push({ date: dateKey, count, inDnd })
  // 聚合窗口固定为 2000ms
  const aggMs = 2000
  if (!pendingTimer)
    pendingTimer = window.setTimeout(flushReminds, Math.max(200, aggMs))
}

// 解析日志文本，驱动倒计时与报警
function processLogMessageForUI(message) {
  // 倒计时
  try {
    const m = String(message).match(/(\d+)\s*秒后/)
    if (m)
      startCountdown(Number.parseInt(m[1]) || 0)
  }
  catch {}
  // 可预约天数
  try {
    // 1) 月度统计（含“可预约 X 天”），老逻辑保留
    const mm = String(message).match(/可预约\s*(\d+)\s*天/)
    // 从全局配置读取阈值
    const onlyRedlink = false // 固定：不限制仅 redlink 才提醒
    if (mm && !onlyRedlink) {
      const n = Number.parseInt(mm[1]) || 0
      if (n > 0) {
        const key = `month:${n}`
        if (shouldRemind(key))
          playAlarm()
      }
    }
    // 2) 新增：时段发现提醒（“🔔 发现可预约时段 N 个（日期 YYYY-MM-DD，示例 HH:MM-HH:MM）”）
    if (/发现可预约时段\s*\d+/.test(message)) {
      const dateMatch = String(message).match(/日期\s*([0-9\-]+)/)
      const countMatch = String(message).match(/发现可预约时段\s*(\d+)/)
      const dateKey = dateMatch ? dateMatch[1] : 'unknown'
      const count = countMatch ? Number.parseInt(countMatch[1]) || 0 : 0
      if (count > 0) {
        const key = `slots:${dateKey}:${count}`
        // 夜间免打扰判断（硬编码：不启用免打扰）
        const inDnd = false

        if (shouldRemind(key)) {
          queueRemind(dateKey, count, inDnd)
        }
      }
    }
  }
  catch {}
}

// 测试：模拟一条“可预约”日志并触发报警
function simulateAvailable() {
  const msg = '📆 测试：2025年10月日历解析完成: 总计 31 天, 可预约 1 天, 休息日 8 天, 约满 20 天, 暂不可约 2 天'
  addLog('success', msg)
  processLogMessageForUI(msg)
  // 直接触发一次 TTS 播报，便于验证语音功能
  try {
    const mm = String(msg).match(/可预约\s*(\d+)\s*天/)
    const n = mm ? Number.parseInt(mm[1]) || 0 : 0
    const body = n > 0 ? `测试：发现可预约 ${n} 天` : '测试：发现可预约'
    speak(body)
  }
  catch {}
}

// 停止倒计时计时器
function stopCountdown() {
  if (countdownTimer) {
    clearInterval(countdownTimer)
    countdownTimer = null
  }
}

// 启动倒计时计时器，从 seconds 开始每秒递减至 0
function startCountdown(seconds) {
  stopCountdown()
  unattendedCountdown.value = Math.max(0, Number(seconds) || 0)
  if (unattendedCountdown.value <= 0)
    return
  countdownTimer = window.setInterval(() => {
    if (unattendedCountdown.value > 0) {
      unattendedCountdown.value -= 1
    }
    else {
      stopCountdown()
    }
  }, 1000)
}

// 以上已前置

// 日志容器引用
const logsContainer = ref(null)

// 选择预约对话框回调
function handleSelectSuccess(list) {
  selectedAppointments.value = Array.isArray(list) ? list : []
  automationSelectedIds.value = selectedAppointments.value.map(a => a.id)
  ElMessage.success(`已选择 ${selectedAppointments.value.length} 条预约数据`)
}

// 处理选择变化（已由弹窗统一处理）

// 开始自动化
async function startAutomation() {
  const unattended = !!automationOptions.value?.unattended
  const scope = String(automationOptions.value?.unattendedScope || 'selected')
  const allowZeroSelection = unattended && scope === 'pending_failed'
  if (selectedAppointments.value.length === 0 && !allowZeroSelection) {
    ElMessage.warning('请先选择要处理的预约数据')
    return
  }

  try {
    const confirmMsg = allowZeroSelection
      ? '确定要启动无人值守（自动抓取待处理/失败）吗？\n后台将自动轮询并处理数据库中 pending/failed 的记录。'
      : `确定要对 ${selectedAppointments.value.length} 条预约数据执行自动化操作吗？`
    await ElMessageBox.confirm(
      confirmMsg,
      '确认执行',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      },
    )

    isRunning.value = true
    automationIsRunning.value = true
    executionLogs.value = []

    addLog('info', '开始自动化预约流程...')
    if (allowZeroSelection) {
      addLog('info', '选择的预约数据: 0 条（自动抓取 pending/failed）')
    }
    else {
      addLog('info', `选择的预约数据: ${selectedAppointments.value.length} 条`)
    }
    addLog('info', `自动化选项: ${JSON.stringify(automationOptions.value)}`)

    // 调用主进程的自动化服务
    // 深拷贝以移除 Vue Proxy，避免 IPC “An object could not be cloned” 错误
    // pending_failed 模式下允许空数组，后端将自动抓取
    const plainAppointments = JSON.parse(JSON.stringify(selectedAppointments.value))
    const plainOptions = JSON.parse(JSON.stringify(automationOptions.value))

    const result = await window.api.automation.start({
      appointments: plainAppointments,
      options: plainOptions,
    })

    // 无人值守模式：立即返回成功，不统计一次性总数
    if (automationOptions.value?.unattended) {
      addLog('success', '无人值守模式已启动，系统将持续执行，日志会实时更新。')
      ElMessage.success('无人值守模式已启动')
      return
    }

    const total = Array.isArray(result.results) ? result.results.length : 0
    const ok = Array.isArray(result.results) ? result.results.filter(r => r.success).length : 0
    const fail = total - ok
    if (total > 0) {
      if (ok === total) {
        addLog('success', `自动化执行完成：全部成功 ${ok}/${total}`)
        ElMessage.success(`自动化执行完成：全部成功 ${ok}/${total}`)
      }
      else if (ok > 0) {
        addLog('warning', `自动化执行完成：部分成功 ${ok}/${total}，失败 ${fail}`)
        ElMessage.warning(`自动化执行完成：部分成功 ${ok}/${total}，失败 ${fail}`)
      }
      else {
        addLog('error', `自动化执行完成：全部失败 ${fail}/${total}`)
        ElMessage.error(`自动化执行完成：全部失败 ${fail}/${total}`)
      }
    }
    else {
      if (result.success) {
        addLog('success', '自动化执行完成')
        ElMessage.success('自动化执行完成')
      }
      else {
        addLog('error', `自动化执行失败: ${result.error}`)
        ElMessage.error(`自动化执行失败: ${result.error}`)
      }
    }
  }
  catch (error: any) {
    if (error !== 'cancel') {
      addLog('error', `执行出错: ${error.message}`)
      ElMessage.error(`执行出错: ${error.message}`)
    }
  }
  finally {
    if (!automationOptions.value?.unattended) {
      isRunning.value = false
      automationIsRunning.value = false
      stopCountdown()
      unattendedCountdown.value = 0
    }
    else {
      // 无人值守保持运行状态，倒计时由日志驱动
      stopCountdown()
    }
  }
}

// 停止自动化
async function stopAutomation() {
  try {
    const result = await window.api.automation.stop()
    if (result.success) {
      addLog('warning', '自动化已停止')
      ElMessage.warning('自动化已停止')
    }
  }
  catch (error: any) {
    ElMessage.error(`停止失败: ${error.message}`)
  }
  finally {
    isRunning.value = false
    automationIsRunning.value = false
    stopCountdown()
    unattendedCountdown.value = 0
    stopAlarm()
  }
}

// 添加日志
function addLog(level: string, message: string) {
  const timestamp = new Date().toLocaleTimeString()
  executionLogs.value.push({
    level,
    message,
    timestamp,
  })

  // 自动滚动到底部
  nextTick(() => {
    const el = logsContainer.value as unknown as HTMLElement | null
    if (el) {
      el.scrollTop = el.scrollHeight
    }
  })
}

// 清空日志
function clearLogs() {
  executionLogs.value = []
}

// 导出日志
function exportLogs() {
  const logText = executionLogs.value
    .map(log => `${log.timestamp} [${log.level.toUpperCase()}] ${log.message}`)
    .join('\n')

  const blob = new Blob([logText], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `automation-logs-${Date.now()}.txt`
  a.click()
  URL.revokeObjectURL(url)
}

// （状态/时间格式化由弹窗内部负责）

// 监听自动化日志事件
onMounted(async () => {
  // 预初始化音频，确保用户交互（点击开始）后可以顺利播放
  setupAlarmAudio()
  // 恢复选择数量提示
  if (Array.isArray(automationSelectedIds.value) && automationSelectedIds.value.length > 0) {
    addLog('info', `已恢复上次选择的 ${automationSelectedIds.value.length} 条记录（在弹窗中可再次调整）`)
  }

  // 恢复运行状态（主进程为准）
  try {
    const st = await window.api.automation.status()
    if (st?.success) {
      const running = !!(st.data?.isRunning)
      isRunning.value = running
      automationIsRunning.value = running
    }
  }
  catch {}

  // 监听来自主进程的日志消息
  removeAutomationLogListener = window.api.automation.onLog((level, message) => {
    addLog(level, message)
    processLogMessageForUI(message)
    // 当检测到“完成/失败/已停止”等关键日志时，确保按钮恢复为可点击
    try {
      if (!automationOptions.value?.unattended) {
        const text = String(message || '')
        if (/自动化流程完成|自动化流程执行失败|已停止/.test(text)) {
          isRunning.value = false
          automationIsRunning.value = false
          stopCountdown()
          unattendedCountdown.value = 0
        }
      }
    }
    catch {}
  })
})

onUnmounted(() => {
  if (removeAutomationLogListener) {
    try {
      removeAutomationLogListener()
    }
    catch {}
    removeAutomationLogListener = null
  }
  stopCountdown()
  stopAlarm()
})
</script>

<template>
  <div class="automation-page">
    <div class="page-header">
      <h1>🤖 自动化预约</h1>
      <p class="page-description">
        使用自动化脚本进行预约操作，支持选择数据库中的预约数据
      </p>
    </div>

    <div class="content-container">
      <!-- 预约数据选择区域（复用弹窗） -->
      <div class="section">
        <h2>📋 选择预约数据</h2>
        <div class="appointment-selector">
          <el-button type="primary" @click="showSelectDialog = true">
            选择预约记录（已选 {{ selectedAppointments.length }} 条）
          </el-button>
        </div>
      </div>

      <!-- 自动化选项区域 -->
      <div class="section">
        <h2>⚙️ 自动化选项</h2>
        <div class="options-container">
          <div class="option-group">
            <h3>基础选项</h3>
            <div class="option-item">
              <el-checkbox v-model="automationOptions.headless">
                无头模式
              </el-checkbox>
              <span class="option-desc">不显示浏览器窗口，后台运行</span>
            </div>
            <div class="option-item">
              <el-checkbox v-model="automationOptions.unattended">
                24小时无人值守模式
              </el-checkbox>
              <span class="option-desc">持续轮询并尝试预约，直至手动停止</span>
            </div>
            <div v-if="automationOptions.unattended" class="option-item">
              <el-input-number
                v-model="automationOptions.unattendedIntervalSeconds"
                :min="0"
                :max="3600"
                :step="5"
                size="small"
              />
              <span class="option-desc">轮询间隔（秒），默认0秒</span>
            </div>
            <div v-if="automationOptions.unattended" class="option-item">
              <el-input-number
                v-model="automationOptions.unattendedPerRecordSeconds"
                :min="1"
                :max="120"
                :step="1"
                size="small"
              />
              <span class="option-desc">同一轮相邻记录间隔（秒），默认5秒</span>
            </div>
            <div v-if="automationOptions.unattended" class="option-item">
              <el-select v-model="automationOptions.unattendedScope" placeholder="处理范围" size="small" style="width: 220px;">
                <el-option label="仅处理已选择记录" value="selected" />
                <el-option label="自动抓取待处理/失败记录" value="pending_failed" />
              </el-select>
              <span class="option-desc">无人值守时的处理对象范围</span>
            </div>
          </div>

          <div class="option-group">
            <h3>测试选项</h3>
            <div class="option-item">
              <el-checkbox v-model="automationOptions.forceSelection">
                强制选择模式
              </el-checkbox>
              <span class="option-desc">强制选择日期和时段（用于测试）</span>
            </div>
            <div v-if="automationOptions.forceSelection" class="option-item">
              <el-input v-model="automationOptions.forceDate" placeholder="强制日期 (DD-MM-YYYY)" size="small" style="width: 200px;" />
              <span class="option-desc">留空则自动选择第一个可用日期</span>
            </div>
            <div v-if="automationOptions.forceSelection" class="option-item">
              <el-input v-model="automationOptions.forceTime" placeholder="强制时间 (HH:MM)" size="small" style="width: 200px;" />
              <span class="option-desc">留空则自动选择第一个可用时段</span>
            </div>
          </div>

          <div v-if="automationOptions.unattended" class="option-group">
            <h3>监控配置（窗口调度）</h3>
            <div class="option-item">
              <el-checkbox v-model="automationOptions.scheduleEnabled">
                启用刻度调度
              </el-checkbox>
              <span class="option-desc">在指定分钟数触发窗口（如 0/15/30/45）</span>
            </div>
            <div v-if="automationOptions.scheduleEnabled" class="option-item">
              <el-select v-model="automationOptions.scheduleMinutesInHour" multiple collapse-tags size="small" style="width: 280px;">
                <el-option :value="0" label="00" />
                <el-option :value="15" label="15" />
                <el-option :value="30" label="30" />
                <el-option :value="45" label="45" />
              </el-select>
              <span class="option-desc">每小时刻度（分钟）</span>
            </div>
            <div v-if="automationOptions.scheduleEnabled" class="option-item">
              <el-input-number v-model="automationOptions.scheduleGuardSeconds" :min="0" :max="120" size="small" />
              <span class="option-desc">刻度窗口守护时间（秒），默认20秒</span>
            </div>
            <div class="option-item">
              <el-checkbox v-model="automationOptions.middayReleaseEnabled">
                启用中午固定窗口
              </el-checkbox>
              <span class="option-desc">工作日 11:55-12:15 强制窗口（优先级最高）</span>
            </div>
            <div v-if="automationOptions.middayReleaseEnabled" class="option-item">
              <el-select v-model="automationOptions.middayReleaseWeekdays" multiple collapse-tags size="small" style="width: 280px;">
                <el-option :value="1" label="周一" />
                <el-option :value="2" label="周二" />
                <el-option :value="3" label="周三" />
                <el-option :value="4" label="周四" />
                <el-option :value="5" label="周五" />
                <el-option :value="6" label="周六" />
                <el-option :value="7" label="周日" />
              </el-select>
              <span class="option-desc">生效工作日（1-周一，7-周日）</span>
            </div>
            <div v-if="automationOptions.middayReleaseEnabled" class="option-item">
              <el-input-number v-model="automationOptions.middayIntervalSeconds" :min="1" :max="60" size="small" />
              <span class="option-desc">中午窗口内轮询间隔（秒），默认2秒</span>
            </div>
            <div class="option-item">
              <el-input-number v-model="automationOptions.intervalInsideWindowSeconds" :min="1" :max="300" size="small" />
              <span class="option-desc">窗口内轮询间隔（秒），默认5秒</span>
            </div>
            <div class="option-item">
              <el-input-number v-model="automationOptions.intervalOutsideWindowSeconds" :min="60" :max="86400" size="small" />
              <span class="option-desc">窗口外轮询间隔（秒），默认600秒</span>
            </div>
            <div class="option-item">
              <el-input-number v-model="automationOptions.maxSleepBeforeWindowSeconds" :min="0" :max="86400" size="small" />
              <span class="option-desc">非窗口期最大等待上限（秒），0表示不限制，默认900秒</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 执行区域 -->
      <div class="section">
        <h2>🚀 执行自动化</h2>
        <div class="execution-container">
          <div class="execution-info">
            <p><strong>已选择:</strong> {{ selectedAppointments.length }} 条预约数据</p>
            <p v-if="selectedAppointments.length > 0">
              <strong>将执行:</strong> 自动化预约流程
            </p>
            <p v-if="automationOptions.unattended && unattendedCountdown > 0" class="text-gray-600">
              下轮将在 {{ unattendedCountdown }} 秒后开始
            </p>
          </div>

          <div class="execution-actions">
            <el-button
              :disabled="((selectedAppointments.length === 0) && !(automationOptions.unattended && automationOptions.unattendedScope === 'pending_failed')) || isRunning"
              :loading="isRunning"
              type="primary"
              size="large"
              @click="startAutomation"
            >
              <i class="el-icon-play" />
              {{ isRunning ? '执行中...' : '开始自动化' }}
            </el-button>

            <el-button
              :disabled="!isRunning"
              type="danger"
              size="large"
              @click="stopAutomation"
            >
              <i class="el-icon-stop" />
              停止执行
            </el-button>

            <!-- 测试按钮：模拟可预约天数，触发语音播放 -->
            <el-button
              size="large"
              @click="simulateAvailable"
            >
              模拟可预约
            </el-button>

            <!-- 控制：手动停止播报 -->
            <el-button
              size="large"
              type="warning"
              :disabled="!isAlarmPlaying && !isTtsSpeaking"
              @click="stopAlarm"
            >
              停止播报
            </el-button>
          </div>
        </div>
      </div>

      <!-- 执行日志区域 -->
      <div v-if="executionLogs.length > 0" class="section">
        <h2>📝 执行日志</h2>
        <div class="logs-container">
          <div class="log-controls">
            <el-button size="small" @click="clearLogs">
              清空日志
            </el-button>
            <el-button size="small" @click="exportLogs">
              导出日志
            </el-button>
          </div>
          <div ref="logsContainer" class="logs-content">
            <div
              v-for="(log, index) in executionLogs"
              :key="index"
              class="log-entry" :class="[`log-${log.level}`]"
            >
              <span class="log-time">{{ log.timestamp }}</span>
              <span class="log-level">[{{ log.level.toUpperCase() }}]</span>
              <span class="log-message">{{ log.message }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- 预约选择弹窗复用 -->
    <AppointmentSelectDialog
      v-model="showSelectDialog"
      batch-id=""
      @success="handleSelectSuccess"
    />
  </div>
</template>

<style scoped>
.automation-page {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.page-header {
  text-align: center;
  margin-bottom: 30px;
}

.page-header h1 {
  font-size: 2.5em;
  color: #409EFF;
  margin-bottom: 10px;
}

.page-description {
  color: #666;
  font-size: 1.1em;
}

.content-container {
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.section {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.section h2 {
  color: #303133;
  margin-bottom: 20px;
  font-size: 1.3em;
}

.selector-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}

.data-count {
  color: #666;
  font-size: 0.9em;
}

.options-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 30px;
}

.option-group h3 {
  color: #409EFF;
  margin-bottom: 15px;
  font-size: 1.1em;
}

.option-item {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.option-desc {
  color: #666;
  font-size: 0.9em;
}

.execution-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.execution-info p {
  margin: 5px 0;
  color: #606266;
}

.execution-actions {
  display: flex;
  gap: 15px;
}

.logs-container {
  border: 1px solid #ddd;
  border-radius: 4px;
  overflow: hidden;
}

.log-controls {
  padding: 10px;
  background: #f5f5f5;
  border-bottom: 1px solid #ddd;
}

.logs-content {
  height: 300px;
  overflow-y: auto;
  padding: 10px;
  background: #fafafa;
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 0.9em;
}

.log-entry {
  margin-bottom: 5px;
  line-height: 1.4;
}

.log-time {
  color: #999;
  margin-right: 10px;
}

.log-level {
  font-weight: bold;
  margin-right: 10px;
}

.log-info .log-level {
  color: #409EFF;
}

.log-success .log-level {
  color: #67C23A;
}

.log-warning .log-level {
  color: #E6A23C;
}

.log-error .log-level {
  color: #F56C6C;
}

.log-message {
  color: #303133;
}

@media (max-width: 768px) {
  .options-container {
    grid-template-columns: 1fr;
  }

  .execution-container {
    flex-direction: column;
    gap: 20px;
    align-items: stretch;
  }
}
</style>
